//
//  WDHelper.swift
//  Woody
//
//  Created by Alean on 2022/11/30.
//

import UIKit
import Zip

//MARK: demo
/**
 zip demo
 //    [WDHelper zipFileWithType:WDFileTypeLogFile fileOutputHandler:^(NSURL * _Nullable url) {
 //        NSLog(@"zip = %@", url);
 //    }];

 unzip demo
 //    NSString *libPath = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) objectAtIndex:0];
 //    NSString *cachePath = [libPath stringByAppendingPathComponent:@"Logs"];
 //    NSURL *fileurl = [NSURL fileURLWithPath:cachePath];
 //    NSURL *zipfileurl = [fileurl URLByAppendingPathComponent:@"logs.zip"];
 //
 //    NSString *zip = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
 //    NSString *cachePathzip = [zip stringByAppendingPathComponent:@"Zips"];
 //    NSURL *localurl = [NSURL fileURLWithPath:cachePathzip];
 //
 //    [WDHelper unzipFileWithZipFilePath:zipfileurl localUrl:localurl password:nil fileOutputHandler:^(NSURL * _Nullable url) {
 //        NSLog(@"unzip = %@", url);
 //    }];
 */

/**********************************************************************************************************************************************/
@objc public enum WDFileType: Int, CaseIterable {
    case logFile = 1
    case voiceFile
    case videoFile
    case imageFile
    case dbFile
    case zipFile
    case gifFile
    case allFile
    
    public var folderName: String {
        get {
            switch self {
            case .logFile:
                return "Logs"
            case .voiceFile:
                return "Voices"
            case .videoFile:
                return "Videos"
            case .imageFile:
                return "Images"
            case .dbFile:
                return "DB"
            case .zipFile:
                return "Zips"
            case .gifFile:
                return "Gifs"
            case .allFile:
                return "*"
            default :
                return "Others"
            }
        }
    }
    
    public var directory: FileManager.SearchPathDirectory {
        get {
            switch self {
            case .voiceFile:
                return .documentDirectory
            case .videoFile:
                return .documentDirectory
            case .dbFile:
                return .documentDirectory
            default :
                return .cachesDirectory
            }
        }
    }
}
public let DBName = "woody.db"

public class WDHelper: NSObject {
    @discardableResult
    @objc public class func ocCacheDirectory(type: WDFileType, directory: FileManager.SearchPathDirectory) throws -> String {
        return try cacheDirectory(type: type, directory: directory)
    }
    
    @discardableResult
    public class func cacheDirectory(type: WDFileType, directory: FileManager.SearchPathDirectory? = nil) throws -> String {
        assert(!(type == .allFile && directory == nil), "WDFileType 为 .allFile 时，directory 不能为nil")
        var directoryType = directory
        if directoryType == nil {
            directoryType = type.directory
        }
        
//        let paths = NSSearchPathForDirectoriesInDomains(directoryType!, FileManager.SearchPathDomainMask.userDomainMask, true)
        var path = (FileManager.default.urls(for: directoryType!, in: .userDomainMask).first?.path ?? FileManager.default.currentDirectoryPath).appending("/")

        if type != .allFile {
            path = path.appending("\(type.folderName)/")
        }

        if !FileManager.default.fileExists(atPath: path) {
            do {
                //withIntermediateDirectories为ture 表示路径中间如果有不存在的文件夹都会创建
                try FileManager.default.createDirectory(atPath: path, withIntermediateDirectories: true, attributes: nil)
            } catch let error {
                throw error
            }
        }
        return path
    }
    //MARK: unzip
    @objc public class func unzipFile(zipFilePath: URL, localUrl: URL, password: String?, fileOutputHandler: @escaping ((_ unzippedFile: URL?) -> Void)) {
        do {
            try cacheDirectory(type: .zipFile)
        } catch let error {
            WDLog(error.localizedDescription, .error)
        }

        do {
            try Zip.unzipFile( zipFilePath,
                destination: localUrl,
                overwrite: true,
                password: password,
                progress: { progress in
                if progress == 1 {
//                    try? FileManager.default.removeItem(at: localUrl)
//                    try? FileManager.default.createDirectory(at: localUrl, withIntermediateDirectories: true, attributes: nil)
                    fileOutputHandler(localUrl)
                }
            }, fileOutputHandler: fileOutputHandler)
        } catch {
            fileOutputHandler(nil)
        }
    }
    //MARK: zip
    @objc public class func zipFile(type: WDFileType, fileOutputHandler: @escaping ((_ zippedFile: URL?) -> Void)) {
        DispatchQueue.main.async {

            if let cacheUrl = FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask).first,
               let logUrl = URL(string: cacheUrl.path + "/" + WDFileType.logFile.folderName) {
                //zip 压缩包路径
                let zipFilePath = logUrl.appendingPathComponent("\(WDFileType.logFile.folderName.lowercased()).zip").path
                if FileManager.default.fileExists(atPath: zipFilePath) {
                    try? FileManager.default.removeItem(atPath: zipFilePath)
                }
                
                var zipFileList = [logUrl]
                
                if let documentUrl = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first {
                    if let dbUrl = URL(string: documentUrl.path + "/" + DBName),
                        FileManager.default.fileExists(atPath: documentUrl.path + "/" + DBName) {
                        zipFileList.append(dbUrl)
                    }
                    
                    if let voiceUrl = URL(string: documentUrl.path + "/" + WDFileType.voiceFile.folderName),
                        FileManager.default.fileExists(atPath: documentUrl.path + WDFileType.voiceFile.folderName) {
                        zipFileList.append(voiceUrl)
                    }
                    
                    if let videoUrl = URL(string: documentUrl.path + "/" + WDFileType.videoFile.folderName),
                       FileManager.default.fileExists(atPath: documentUrl.path + WDFileType.videoFile.folderName) {
                       zipFileList.append(videoUrl)
                   }
                }
                
                try? Zip.zipFiles(paths: zipFileList, zipFilePath: URL(fileURLWithPath: zipFilePath), password: nil, progress: { progress in
                    if progress == 1.0 {
                        print("压缩成功")
                        fileOutputHandler(URL(fileURLWithPath: zipFilePath))
                    }
                })
            }

        }
    }

    @objc public class func cleanAppCache(calculatedCompletionHander: @escaping () -> Void) {
        DispatchQueue.global().async {
            
            let voiceSize = WDFileCache.travelCachedSize(type: .voiceFile)
            let videoSize = WDFileCache.travelCachedSize(type: .videoFile)
            let dbSize = WDFileCache.travelCachedSize(type: .dbFile)
            let allDoc = WDFileCache.travelCachedSize(type: .allFile, directory: .documentDirectory)
            let otherDocSize = allDoc - voiceSize - videoSize

            let imageSize = WDFileCache.travelCachedSize(type: .imageFile)
            let logSize = WDFileCache.travelCachedSize(type: .logFile)
            let zipSize = WDFileCache.travelCachedSize(type: .zipFile)
            let gifSize = WDFileCache.travelCachedSize(type: .gifFile)
            let allCache = WDFileCache.travelCachedSize(type: .allFile, directory: .cachesDirectory)
            let otherCacheSize = allCache - logSize - zipSize - gifSize - imageSize

            DispatchQueue.main.async {
                calculatedCompletionHander()
                print("allDoc \(allDoc) = voiceSize \(voiceSize) + voiceSize \(voiceSize) + dbSize\(dbSize) + otherDocSize \(otherDocSize)")
                print("allCache \(allCache) = imageSize \(imageSize) + logSize \(logSize) + zipSize \(zipSize) + gifSize \(gifSize) + otherCacheSize \(otherCacheSize)")
            }
        }
    }
    
    public class func doClearCache(cleanTypes: [WDFileType]) {
        let dispatchGroup = DispatchGroup()
        if cleanTypes.contains(.allFile) {
            dispatchGroup.enter()
            DispatchQueue.global().async {
                WDFileCache.removeCached(type: .allFile, directory: .cachesDirectory)
                dispatchGroup.leave()
            }
            
            dispatchGroup.enter()
            DispatchQueue.global().async {
                WDFileCache.removeCached(type: .allFile, directory: .documentDirectory)
                dispatchGroup.leave()
            }
        } else {
            for type in cleanTypes {
                dispatchGroup.enter()
                DispatchQueue.global().async {
                    WDFileCache.removeCached(type: type)
                    dispatchGroup.leave()
                }
            }
        }

        dispatchGroup.notify(queue: DispatchQueue.main) {
            print("清除缓存操作成功")
        }
    }
}
